{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# API 키를 환경변수로 관리하기 위한 설정 파일\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# API 키 정보 로드\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# LangSmith 추적을 설정합니다. https://smith.langchain.com\n",
    "# !pip install -qU langchain-teddynote\n",
    "from langchain_teddynote import logging\n",
    "\n",
    "# 프로젝트 이름을 입력합니다.\n",
    "logging.langsmith(\"CH15-React-Agent\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## React Agent\n",
    "\n",
    "![](assets/agent.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_teddynote.tools.tavily import TavilySearch\n",
    "from langchain_core.messages import HumanMessage\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "\n",
    "# 메모리 설정\n",
    "memory = MemorySaver()\n",
    "\n",
    "# 모델 설정\n",
    "model = ChatOpenAI(model_name=\"gpt-4o-mini\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 도구 설정"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 웹 검색\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.tools.tavily import TavilySearch\n",
    "\n",
    "\n",
    "web_search = TavilySearch(\n",
    "    topic=\"general\",  # 뉴스 주제 (general 또는 news)\n",
    "    max_results=5,  # 최대 검색 결과\n",
    "    include_answer=False,\n",
    "    include_raw_content=False,\n",
    "    include_images=False,\n",
    "    format_output=False,  # 결과 포맷팅\n",
    ")\n",
    "\n",
    "web_search.name = \"web_search\"\n",
    "web_search.description = (\n",
    "    \"Use this tool to search on the web for any topic other than news.\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "result = web_search.search(\"SK AI SUMMIT 2024 관련된 정보를 찾아줘\")\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 파일 관리\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.agent_toolkits import FileManagementToolkit\n",
    "\n",
    "# 'tmp'라는 이름의 디렉토리를 작업 디렉토리로 설정합니다.\n",
    "working_directory = \"tmp\"\n",
    "\n",
    "# FileManagementToolkit 객체를 생성합니다.\n",
    "file_management_tools = FileManagementToolkit(\n",
    "    root_dir=str(working_directory),\n",
    ").get_tools()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 파일 관리 도구 출력\n",
    "file_management_tools"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Retriever 도구"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "from langchain_community.vectorstores import FAISS\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.document_loaders import PDFPlumberLoader\n",
    "\n",
    "# PDF 파일 로드. 파일의 경로 입력\n",
    "loader = PDFPlumberLoader(\"data/SPRI_AI_Brief_2023년12월호_F.pdf\")\n",
    "\n",
    "# 텍스트 분할기를 사용하여 문서를 분할합니다.\n",
    "text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)\n",
    "\n",
    "# 문서를 로드하고 분할합니다.\n",
    "split_docs = loader.load_and_split(text_splitter)\n",
    "\n",
    "# VectorStore를 생성합니다.\n",
    "vector = FAISS.from_documents(split_docs, OpenAIEmbeddings())\n",
    "\n",
    "# Retriever를 생성합니다.\n",
    "pdf_retriever = vector.as_retriever()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.tools.retriever import create_retriever_tool\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "# PDF 문서를 기반으로 검색 도구 생성\n",
    "retriever_tool = create_retriever_tool(\n",
    "    pdf_retriever,\n",
    "    \"pdf_retriever\",\n",
    "    \"Search and return information about SPRI AI Brief PDF file. It contains useful information on recent AI trends. The document is published on Dec 2023.\",\n",
    "    document_prompt=PromptTemplate.from_template(\n",
    "        \"<document><context>{page_content}</context><metadata><source>{source}</source><page>{page}</page></metadata></document>\"\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "도구 목록을 정의합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [web_search, *file_management_tools, retriever_tool]\n",
    "tools"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 에이전트 생성"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph.prebuilt import create_react_agent\n",
    "\n",
    "agent_executor = create_react_agent(model, tools, checkpointer=memory)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "에이전트를 시각화 합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.graphs import visualize_graph\n",
    "\n",
    "visualize_graph(agent_executor)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 출력 함수 정의"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.messages import stream_graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Config 설정\n",
    "config = {\"configurable\": {\"thread_id\": \"abc123\"}}\n",
    "inputs = {\"messages\": [(\"human\", \"안녕? 내 이름은 테디야\")]}\n",
    "\n",
    "# 그래프 스트림\n",
    "stream_graph(agent_executor, inputs, config, node_names=[\"agent\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"abc123\"}}\n",
    "inputs = {\"messages\": [(\"human\", \"내 이름이 뭐라고?\")]}\n",
    "\n",
    "# 그래프 스트림\n",
    "stream_graph(agent_executor, inputs, config, node_names=[\"agent\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"abc123\"}}\n",
    "inputs = {\n",
    "    \"messages\": [\n",
    "        (\"human\", \"AI Brief 보고서에서 Anthropic 투자 관련된 정보를 요약해줘.\")\n",
    "    ]\n",
    "}\n",
    "stream_graph(agent_executor, inputs, config, node_names=[\"agent\", \"tools\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"abc123\"}}\n",
    "inputs = {\n",
    "    \"messages\": [\n",
    "        (\n",
    "            \"human\",\n",
    "            \"한강 작가의 노벨상 수상 관련된 뉴스를 검색하고 보고서 형식에 맞게 작성해줘\",\n",
    "        )\n",
    "    ]\n",
    "}\n",
    "stream_graph(agent_executor, inputs, config, node_names=[\"agent\", \"tools\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "instruction = \"\"\"\n",
    "당신의 임무는 `보도자료`를 작성하는 것입니다.\n",
    "----\n",
    "다음의 내용을 순서대로 처리해 주세요.\n",
    "1. `한강 작가의 노벨상 수상` 관련된 뉴스를 검색해 주세요.\n",
    "2. 노벨상 수상 관련 뉴스를 바탕으로 보고서 / 보드자료 작성해 주세요.\n",
    "3. 단, 중간에 요점 정리를 위한 markdown 테이블 형식 요약을 적극 활용해 주세요.\n",
    "4. 출력 결과를 파일로 저장해 주세요. (파일 이름은 \"agent_press_release.md\")\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config = {\"configurable\": {\"thread_id\": \"abc123\"}}\n",
    "inputs = {\"messages\": [(\"human\", instruction)]}\n",
    "stream_graph(agent_executor, inputs, config, node_names=[\"agent\", \"tools\"])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain-kr-lwwSZlnu-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
